package anc.tankshooter.models;

import java.util.ArrayList;
import java.util.Random;

import anc.tankshooter.GameActivity;
import anc.tankshooter.GameSetting;
import anc.tankshooter.map.AstartFinder;
import anc.tankshooter.map.AstartNode;
import anc.tankshooter.map.GameMap;
import anc.tankshooter.models.Bullet.BulletType;

/**
 * Đối tượng tương trưng cho xe tăng địch.
 * @author tauitdnmd
 *
 */
public class Enermy extends ITank{

	public static enum EnermyType{STATIC,NORMAL,FAST,HEAVY,BOSS}
	private AstartFinder mPathFinder = new AstartFinder();
	private static Random mRandom = new Random(System.nanoTime());
	
	private ArrayList<AstartNode> mPath;
	private EnermyType mType;
	private float mPointToShoot;
	
	public Enermy(EnermyType type,float pX, float pY) {
		super(pX, pY);
		mPointToShoot = 0;
		isMoving=false;
		
		mDurations = new long[] { 100, 100, 100, 100, 100, 100, 100, 100 };
		mFrames = new int[8];
		mLoopCounter=-1;
		setType(type);
	}
	
	public float getSearchRange(){
		return mSearchRange;
	}
	
	public void setSearchRange(float range){
		mSearchRange = range;
	}
	
	@Override
	public void onUpdate(GameMap map,float elapseSecond) {
		
		switch(getType()){
		case STATIC:
			move();
			break;
		case FAST:
			updateFastTank(map, elapseSecond);
			break;
		case NORMAL:
		case HEAVY:
		case BOSS:
			int[][] matrix = map.getMatrix();
			if(!isMoving ){
				if((mPath==null|| mPath.size()<=0)&& mTargetTank !=null ) {
					int i1 = (int)(mY/GameMap.TITLE_HEIGHT);
					int j1 = (int)(mX/GameMap.TITLE_WIDTH);
					int i2 = (int)(mTargetTank.getY()/GameMap.TITLE_HEIGHT);
					int j2 = (int)(mTargetTank.getX()/GameMap.TITLE_WIDTH);
					findPathAsync(matrix.clone(),i1,j1,i2,j2);
				}
				if(mPath!=null && mPath.size()>0){
					moveAstarPath();
				}else {
					// Nếu đụng tường, ngẫu nhiêu yêu cần đổi hướng
					// Và luôn luôn có 1 hướng đi được . Thì thay đổi hướng
					while((mRandom.nextInt(30)/3 == 0|| this.isTouchEdge() /*|| !checkMove(map)*/) 
							&& hasMovingDirection(map)) {
						randomDirection();
					}
					
				}
				
				if(checkMove(map)){
					matrix[nPY][nPX] = 1;
					isMoving = true;
				}else {
					if(mPath!=null)
						mPath.clear();
				}
			}
			break;
		}
		
		mPointToShoot += elapseSecond;
		if( mPointToShoot>=4 && mRandom.nextInt(3)==0) {
			mPointToShoot = 0;
			mIsAutoShoot = true;
		}
		
		super.onUpdate(map, elapseSecond);
	}
	
	private void updateFastTank(GameMap map,float elapseSecond){
		int[][] matrix = map.getMatrix();
		
		if(!isMoving){
			// Nếu đụng tường, ngẫu nhiêu yêu cần đổi hướng
			// Và luôn luôn có 1 hướng đi được . Thì thay đổi hướng
			while((mRandom.nextInt(30)/3 == 0|| this.isTouchEdge()|| !checkMove(map)) 
					&& hasMovingDirection(map)) {
				randomDirection();
			}
			if(checkMove(map)){
				matrix[nPY][nPX] = 1;
				isMoving = true;
			}
		}
	}
	
	/**
	 * Chuyển hướng theo đường đi của thuật toán A*
	 */
	private void moveAstarPath(){
		int nx = (int)mX/GameMap.TITLE_WIDTH;
		int ny = (int)mY/GameMap.TITLE_HEIGHT;
		AstartNode node = mPath.get(0); mPath.remove(0);
		if(mPath.size()<=0)
			mPointToShoot+=30;
		if(node.i>ny)
			setDir(MovingDirection.DOWN);
		else if(node.i<ny)
			setDir(MovingDirection.UP);
		else if(node.j>nx)
			setDir(MovingDirection.RIGHT);
		else setDir(MovingDirection.LEFT);
		
	}
	
	private void findPathAsync(final int[][] matrix,final int i1,final int j1,
					final int i2,final int j2){
		Enermy.this.setIsFindding(true);
		new Thread(new Runnable() {
		
			@Override
			public void run() {
				
				ArrayList<AstartNode> path = mPathFinder.find(matrix.clone(),i1,j1,i2,j2);
				mPath = path;
				setIsFindding(false);
			}
		}).start();
	}
	/**
	 * Chuyển hướng ngẫu nhiên
	 */
	private void randomDirection(){
		
		switch(mRandom.nextInt(4)){
		case 0:
			setDir(MovingDirection.UP);
			break;
		case 1:
			setDir(MovingDirection.RIGHT);
			break;
		case 2:
			setDir(MovingDirection.DOWN);
			break;
		case 3:
			setDir(MovingDirection.LEFT);
			break;
		}
	}
	
	@Override
	public void reset() {
		// TODO Auto-generated method stub
		super.reset();
		isMoving = false;
		isShockBack=false;
	}

	public EnermyType getType() {
		return mType;
	}

	/**
	 * Thay đổi loại xa tăng địch
	 * @param mType
	 */
	public void setType(EnermyType mType) {
		this.mType = mType;
		int startFrame = 0;
		switch(getType()){
		case STATIC:
			mHeart=1;
			break;
		case NORMAL:
			mHeart = 1;
			mSearchRange = 128;
			setSpeed(GameSetting.SPEED_ENERMY_NORMAL);
			startFrame = 5+mRandom.nextInt(3);
			for (int i = 0; i < mFrames.length; i++) {
				mFrames[i]=startFrame*8+i;
			}
			break;
		case FAST:
			mHeart = 1;
			mSearchRange = 128;
			setSpeed(GameSetting.SPEED_ENERMY_FAST);
			startFrame = 2+mRandom.nextInt(1);
			for (int i = 0; i < mFrames.length; i++) {
				mFrames[i]=startFrame*8+i;
			}
			break;
		case HEAVY:
			mHeart = 1;
			mSearchRange = 160;
			setSpeed(GameSetting.SPEED_ENERMY_HEAVY);
			startFrame = 3+mRandom.nextInt(2);
			for (int i = 0; i < mFrames.length; i++) {
				mFrames[i]=startFrame*8+i;
			}
			break;
		case BOSS:
			mHeart = 2;
			mSearchRange = 300;
			setSpeed(GameSetting.SPEED_ENERMY_BOSS);
			this.setBulletType(BulletType.LASER);
			startFrame =GameActivity.mGlobalSetting.getCurrentLevel()<=2?8:9;
			for (int i = 0; i < mFrames.length; i++) {
				mFrames[i]=startFrame*8+i;
			}
			break;
		}
		this.start();
	}

	
	

}
